Home:ALL Converter>Recursive search on a collection in MongoDB

Recursive search on a collection in MongoDB

Ask Time:2016-11-10T19:10:43         Author:RaR

Json Formatter

I have a list of documents in MongoDB with tree structure, where Model Tree Structures with Parent References pattern used. I want a single aggregation query which returns ancestor list(till the root), given the 'name' property.

Structure:

{
  '_id': '1',
  'name': 'A',
  'parent': '',
},
{
  '_id': '2',
  'name': 'B',
  'parent': 'A',
},
{
  '_id': '3',
  'name': 'C',
  'parent': 'B',
},
{
  '_id': '4',
  'name': 'D',
  'parent': 'C',
}

Aggregation result:(Given, name = 'D')

{
  '_id': '4',
  'name': 'D',
  'ancestors': [{name:'C'}, {name:'B'}, {name:'A'}]
}

Note: I can't change the document structure now. It will cause many problems. I saw many solutions which suggest to use Model Tree Structures with an Array of Ancestors. But I cannot use it now. Is there any way to achieve it with the above pattern using single aggregation query? Thank you

Author:RaR,eproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/40526148/recursive-search-on-a-collection-in-mongodb
styvane :

Starting from MongoDB 3.4, we can do this with the Aggregation Framework.\n\nThe first and most important stage in our pipeline is the $graphLookup stage. $graphLookup allows us to recursively match on the \"parent\" and \"name\" field. As result, we get the ancestors of each \"name\".\n\nThe next stage in the pipeline is the $match stage where we simply select the \"name\" we are interested in.\n\nThe final stage is the $addFields or $project stage where we apply an expression to the \"ancestors\" array using the $map array operator.\n\nOf course with the $reverseArray operator we reverse our array in order to get the expected result. \n\ndb.collection.aggregate(\n [ \n { \"$graphLookup\": { \n \"from\": \"collection\", \n \"startWith\": \"$parent\", \n \"connectFromField\": \"parent\", \n \"connectToField\": \"name\", \n \"as\": \"ancestors\"\n }}, \n { \"$match\": { \"name\": \"D\" } }, \n { \"$addFields\": { \n \"ancestors\": { \n \"$reverseArray\": { \n \"$map\": { \n \"input\": \"$ancestors\", \n \"as\": \"t\", \n \"in\": { \"name\": \"$$t.name\" }\n } \n } \n }\n }}\n ]\n)\n",
2016-11-10T13:14:20
yy